package baiqitun.stupro.api.controller;

import baiqitun.stupro.common.exception.enums.support.StuproExceptionEnum;
import baiqitun.stupro.common.exception.enums.support.NotFoundExceptionEnum;
import baiqitun.stupro.common.entity.impl.SysFile;
import baiqitun.stupro.common.exception.support.ExistedException;
import baiqitun.stupro.common.exception.support.NotFoundException;
import baiqitun.stupro.common.exception.StuproException;
import baiqitun.stupro.common.model.Result;
import baiqitun.stupro.common.service.system.SysFileService;
import baiqitun.stupro.common.util.AuthUtil;
import baiqitun.stupro.common.util.IdsUtil;
import baiqitun.stupro.common.util.ResultUtil;
import baiqitun.stupro.common.util.UploadUtil;
import baiqitun.stupro.common.validate.group.SaveGroup;
import baiqitun.stupro.common.validate.group.UpdateGroup;
import baiqitun.stupro.project.constant.SysProjectTypeEnum;
import baiqitun.stupro.project.core.document.entity.SysProjectDocument;
import baiqitun.stupro.project.core.document.service.SysProjectDocumentService;
import baiqitun.stupro.project.core.news.SysProjectNews;
import baiqitun.stupro.project.core.news.service.SysProjectNewsService;
import baiqitun.stupro.project.entity.SysProject;
import baiqitun.stupro.project.service.*;
import baiqitun.stupro.security.entity.SysUser;
import baiqitun.stupro.security.service.SysUserService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * 项目控制器
 * @author kedaji
 */
@RequestMapping("/project")
@Api(description = "项目控制器")
@Slf4j
@Controller
public class ProjectController {
    @Autowired
    private SysFileService sysFileService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysProjectService sysProjectService;
    @Autowired
    private SysProjectUserService sysProjectUserService;
    @Autowired
    private SysProjectFileService sysProjectFileService;
    @Autowired
    private SysProjectUserRoleService sysProjectUserRoleService;
    @Autowired
    private SysProjectDocumentService sysProjectDocumentService;
    @Autowired
    private SysProjectBrowseService sysProjectBrowseService;
    @Autowired
    private SysProjectNewsService sysProjectNewsService;
    @Autowired
    private SysProjectLikeService sysProjectLikeService;

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("获取一个项目的基本信息")
    @GetMapping("/{id}")
    public Result<SysProject> getById(@PathVariable("id") String projectId){
        return ResultUtil.ok(sysProjectService.getExistedEntity(projectId, new NotFoundException(NotFoundExceptionEnum.PERMISSION_NOT_FOUND)));
    }

//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation("获取项目成员信息")
//    @GetMapping("/{id}")
//    public Result<List> getMember(@PathVariable("id") String projectId){
//
//    }


    // TODO 所有用户对项目的操作将被更新到项目动态中
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("创建项目")
    @PostMapping
    public Result<?> saveProject(Authentication authentication,
                                        @ApiParam("项目信息") @Validated(SaveGroup.class) SysProject project,
                                        @ApiParam("项目说明文档") @Validated(SaveGroup.class)SysProjectDocument projectDocument){
        String username = AuthUtil.getUsername(authentication);
        project.setCreateBy(username);
        projectDocument.setCreateBy(username);
        if (SysProjectTypeEnum.FREE.getValue().equals(project.getType())){
            // 创建普通项目
            sysProjectUserRoleService.saveFreeProject(project, projectDocument);
        } else if (SysProjectTypeEnum.SUBJECT.getValue().equals(project.getType())){
            // 创建一生一品项目
            sysProjectUserRoleService.saveSubjectProject(project, projectDocument);
        }

        return ResultUtil.ok();
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("删除项目")
    @DeleteMapping
    public Result<?> removeById(Authentication authentication,
                                @ApiParam("项目id") @NotBlank(message = "项目id不能为空") String projectId){
        String username = AuthUtil.getUsername(authentication);
        sysProjectUserRoleService.removeById(projectId, username);
        return ResultUtil.ok();
    }

    /**
     * TODO 对所有ids都要添加@Partten的数据校验注解
     */
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("邀请学生加入项目")
    @PostMapping("/student")
    public Result<?> inviteStudent(Authentication authentication,
                            @ApiParam("项目id") @NotBlank(message = "项目id不能为空") String projectId,
                            @ApiParam("被邀请的学生id序列") String userIds,
                            @ApiParam("备注") String description){
        // TODO 邀请学生时一生一品项目只能邀请当前导师的学生
        String username = AuthUtil.getUsername(authentication);
        SysUser user = sysUserService.getUserByUsername(username);
        List<String> ids = IdsUtil.parser(userIds);
        sysProjectUserRoleService.inviteStudents(projectId, user.getId(), ids, description);
        return ResultUtil.ok();
    }

    /**
     * 只有管理员才有的权限
     */
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("邀请导师加入项目")
    @PostMapping("/tutor")
    public Result<?> inviteTutor(Authentication authentication,
                                @ApiParam("项目id") @NotBlank(message = "项目id不能为空") String projectId,
                                @ApiParam("被邀请的学生id序列") String tutorUserIds,
                                @ApiParam("备注") String description){
        String username = AuthUtil.getUsername(authentication);
        SysUser user = sysUserService.getUserByUsername(username);
        List<String> ids = IdsUtil.parser(tutorUserIds);
        sysProjectUserRoleService.inviteTutors(projectId, user.getId(),ids, description);
        return ResultUtil.ok();
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("查询项目的指导教师")
    @GetMapping("/tutor")
    public Result<List<SysUser>> listTutor(@ApiParam("项目id") @NotBlank(message = "项目id不能为空") String projectId){
        return ResultUtil.ok(sysProjectUserService.listTutorByProjectId(projectId));
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("查询项目说明文档")
    @GetMapping("/document")
    public Result<SysProjectDocument> getDocumentByProjectId(@ApiParam("项目id") @NotBlank(message = "项目id不能为空") String projectId){
        SysProject project = sysProjectService.getExistedEntity(projectId, new NotFoundException(NotFoundExceptionEnum.PROJECT_NOT_FOUND));
        SysProjectDocument document = sysProjectDocumentService.getById(project.getDocumentId());
        if (document == null){
            throw new StuproException(StuproExceptionEnum.UNKNOWN).put(SysProject.class, "id", project.getId()).put(SysProjectDocument.class, "#", null);
        }
        return ResultUtil.ok(document);
    }

    /**
     * 只有管理员才有的权限
     */
    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("修改项目说明文档")
    @PutMapping("/document")
    public Result<?> updateDocument(Authentication authentication, @Validated(UpdateGroup.class) SysProjectDocument document,
                                    @ApiParam("项目id") String projectId){
        String username = AuthUtil.getUsername(authentication);
        SysProject project = sysProjectService.getExistedEntity(projectId, new NotFoundException(NotFoundExceptionEnum.PROJECT_NOT_FOUND));
        document.setId(project.getDocumentId()).setCreateBy(username);
        sysProjectDocumentService.save(document);
        return ResultUtil.ok();
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("修改项目信息")
    @PutMapping
    public Result<?> updateProject(Authentication authentication,
                                   @ApiParam("项目信息") @Validated(UpdateGroup.class) SysProject project){
        String username = AuthUtil.getUsername(authentication);
        project.setType(null);
        project.setUpdateBy(username);
        sysProjectService.updateById(project);
        return ResultUtil.ok();
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("上传文件")
    @PostMapping("/file")
    public Result<?> upload(Authentication authentication, HttpServletRequest request) throws IOException {
        MultipartFile single = UploadUtil.single(request);
        String username = AuthUtil.getUsername(authentication);
        InputStream inputStream = single.getInputStream();
        SysFile file = new SysFile();
        SysUser user = sysUserService.getUserByUsername(username);
        if (user == null){
            throw new NotFoundException(NotFoundExceptionEnum.USER_NOT_FOUND).put(SysUser.class, "username", username);
        }
        file.setFilename(single.getOriginalFilename()).setUserId(user.getId()).setCreateBy(username);
        sysFileService.save(file, inputStream);
        return ResultUtil.ok();
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("分页查询项目动态")
    @GetMapping("/news")
    public Result<IPage<SysProjectNews>> pageNews(Integer pageNo, Integer pageSize, SysProjectNews news){
        IPage<SysProjectNews> page = sysProjectNewsService.page(pageNo, pageSize, news);
        return ResultUtil.ok(page);
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("分页查询项目所有上传的文件")
    @GetMapping("/file")
    public Result<IPage<SysFile>> pageFiles(String projectId, Integer pageNo, Integer pageSize){
        IPage<SysFile> page = sysProjectFileService.pageFileByProjectId(projectId, pageNo, pageSize);
        return ResultUtil.ok(page);
    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("分页查询我在这个项目上传的文件")
    @GetMapping("/file/me")
    public Result<IPage<?>> pageFilesForMe(Authentication authentication, String projectId, Integer pageNo, Integer pageSize){
        SysUser user = sysUserService.getEnabledUserByUsername(AuthUtil.getUsername(authentication));
        try {
            // 检查我是不是这个项目的成员
            sysProjectUserService.checkRelationExisted(projectId, user.getId());
            //如果没抛出异常
            throw new StuproException(StuproExceptionEnum.ILLEGAL_OPERATION).put(SysUser.class, "username", user.getUsername());
        } catch (ExistedException e){
            // 如果抛出Existed异常，说明已存在，检查通过
            IPage<SysFile> filePage = sysProjectFileService.pageUserFileByProjectId(projectId, user.getUsername(), pageNo, pageSize);
            return ResultUtil.ok(filePage);
        }
    }

//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation("分页查询项目的任务列表")
//    @GetMapping("/task")
//    public Result<List<TreeModel<Task>>> taskTrees(Integer pageNo, Integer pageSize){
//        return ResultUtil.ok();
//    }
//
//    /**
//     * 只有管理员或导师才有的权限
//     */
//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation("创建一个等待领取的任务")
//    @PostMapping("/task")
//    public Result<?> saveTask(Authentication authentication, String taskName, String description){
//
//        return ResultUtil.ok();
//    }
//    /**
//     * 只有管理员或导师才有的权限
//     */
//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation("任务指派")
//    @PostMapping("/task/user")
//    public Result<?> task(Authentication authentication){
//        return ResultUtil.ok();
//    }
//    /**
//     * 只有管理员或导师才有的权限
//     */
//    @ResponseStatus(HttpStatus.OK)
//    @ApiOperation("创建子任务")
//    @PostMapping("/task/sub")
//    public Result<?> saveSubTask(Authentication authentication, String taskId, String name){
//        return ResultUtil.ok();
//    }

    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("点赞")
    @PostMapping("/like")
    public Result<?> like(Authentication authentication, String projectId){
        SysUser user = sysUserService.getEnabledUserByUsername(AuthUtil.getUsername(authentication));
        sysProjectLikeService.like(user.getId(), projectId, user.getUsername());
        return ResultUtil.ok();
    }


    @ResponseStatus(HttpStatus.OK)
    @ApiOperation("添加项目浏览记录")
    @PostMapping("/browse")
    public Result<?> browse(Authentication authentication, String projectId){
        SysUser user = sysUserService.getEnabledUserByUsername(AuthUtil.getUsername(authentication));
        sysProjectBrowseService.browse(user.getId(), projectId, user.getUsername());
        return ResultUtil.ok();
    }
}